home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PROGRAMM / CC_C / 0151.ZIP / SCAV23X.ASM < prev    next >
Assembly Source File  |  1985-07-12  |  10KB  |  461 lines

  1. title scavenge Copyright (c) T. Jennings 1983
  2. ;
  3. ;****************************************
  4. ;*                    *
  5. ;*        SCAVENGE        *
  6. ;*                    *
  7. ;*    Mark bad blocks on MSDOS     *
  8. ;*    as allocated in the FAT.    *
  9. ;*                    *
  10. ;*    T. Jennings 12 July 85        *
  11. ;*      created 15 Sept. 82        *
  12. ;*                    *
  13. ;****************************************
  14. ;
  15. ;Reads all sectors in logical MSDOS blocks
  16. ;and marks the file allocation tables such
  17. ;that the blocks are permanently allocated
  18. ;where CHKDSK will not deallocate them.
  19. ;
  20. ;
  21. ;This version works on any 2.xx or 3.xx MSDOS,
  22. ;PCDOS, on any media type, fixed or removable.
  23. ;One (major) limitation: it will not map out
  24. ;blocks that are already allocated to a file;
  25. ;it will say "block used", but won't tell you
  26. ;which file it is in.
  27. ;
  28. ;If SCAVENGE finds any bad blocks, it will ask
  29. ;you whether or not you want the disk updated.
  30. ;You can safely run it just to see if the disk 
  31. ;is OK.
  32. ;
  33. ;MASM, LINK, then EXE2BIN this to make a COM
  34. ;file. It will not run as an EXE file. NOTE:
  35. ;LINK will give you a 'Warning: no STACK 
  36. ;segment' error: ignore it.
  37. ;
  38. cr    equ    0dh
  39. lf    equ    0ah
  40. page
  41. cgroup group code
  42. code segment byte public 'code'
  43. assume cs:cgroup,ds:cgroup,ss:cgroup
  44. ;
  45. ;MSDOS page 0 stuff.
  46. ;
  47.     org    5ch
  48. tfcb label byte
  49.  
  50.     org    80h
  51. tbuff label byte
  52.  
  53.     org    100h
  54. scavenge:
  55.     jmp    start
  56. ;
  57. ;Disk parameters:
  58. ;
  59. blkcnt    dw    (0)    ;blocks this disk
  60. blksize    dw    (0)    ;sectors per block
  61. secsize    dw    (0)    ;phys. sector size
  62. badcnt    dw    (0)    ;# bad blocks found
  63. newbad    dw    (0)    ;new bad ones
  64. block    dw    (0)    ;current block
  65. sector    dw    (0)    ;sector to read
  66. disk    db    (0)    ;selected disk
  67. curdsk    db    (0)    ;current disk.
  68. fatsec    dw    (0)    ;1st FAT sector,
  69. fatcnt    dw    (0)    ;FAT sec count.
  70.  
  71. fat16    db    (0)    ;1 == 16 bit FAT
  72. blkdsp    db    (0)    ;display counter
  73.  
  74.     dw 128 dup (0)
  75. stack    dw    (0)    ;what else
  76. page
  77. ;
  78. ;Say who we are, describe the disk we are
  79. ;about to fix, ask to continue or abort.
  80. ;
  81. start:    mov    ax,cs
  82.     mov    ds,ax
  83.     mov    ss,ax
  84.     mov    sp,offset stack
  85.  
  86.     mov    dx,offset signon
  87.     call    pstr
  88.     call    setup        ;get disk stuff
  89.     jnc    st1
  90.     call    pstr
  91.     int    32        ;error.
  92.  
  93. st1:    call    liststat    ;describe dsk
  94.     mov    dx,offset contstr
  95.     call    pstr        ;type any key..
  96.     call    ina
  97. ;
  98. ;Find all the bad blocks, if any, display them,
  99. ;ask if we should update the FAT. If so, write
  100. ;it out.
  101. ;
  102.     mov    dx,offset crlf
  103.     call    pstr
  104.     call    findbad        ;map bad,
  105.     call    listbad        ;list them,
  106.     cmp    newbad,0    ;if new bad
  107.     je    st2        ;blocks...
  108.  
  109. st1a:    mov    dx,offset updstr ;ask if we
  110.     call    pstr        ;should update
  111.     call    ina
  112.     and    al,5fh
  113.     cmp    al,'N'
  114.     je    st2
  115.     cmp    al,'Y'
  116.     jne    st1a
  117.  
  118.     mov    al,disk        ;write out the
  119.     mov    dx,fatsec    ;FAT,
  120.     mov    cx,fatcnt
  121.     mov    bx,offset fatbuf
  122.     int    26h
  123.     pop    ax        ;pop flags
  124.  
  125. st2:    mov    al,curdsk    ;reselect the
  126.     call    seldsk        ;original disk
  127.     int    32
  128.  
  129. signon    db    cr,lf,'DOS version 2, 3 Bad Sector Mapper'
  130.     db    cr,lf,'T. Jennings 12 July 85'
  131.     db    cr,lf,'    Reads all blocks on the disk, and marks'
  132.     db    cr,lf,'    unused bad ones in the FAT so that MSDOS'
  133.     db    cr,lf,'    will not use them later. It will not touch'
  134.     db    cr,lf,'    files with bad blocks; COPY the file to'
  135.     db    cr,lf,'    save what you can, DELete it, then run'
  136.     db    cr,lf,'    SCAVENGE to map out the bad block.'
  137.     db    '$'
  138. contstr    db    cr,lf,'Type ^C to abort, any '
  139.     db    'other key to continue: $'
  140. updstr    db    cr,lf,lf,' Want the disk updated? [y,n] :$'
  141. crlf    db    cr,lf,'$'
  142. page
  143. ;
  144. ;Get the data on the specified disk. Return 
  145. ;carry if no drive specified. Returns ES:DI
  146. ;pointing to the FAT for the selected drive.
  147. ;
  148. setup:    mov    dx,offset wtstr
  149.     call    pstr
  150.     call    initdsk        ;reset dsk sys,
  151.     call    getdsk        ;get current,
  152.     mov    curdsk,al    ;save it,
  153.     mov    al,tfcb        ;make sure a
  154.     cmp    al,0        ;new one spec'd
  155.     stc            ;quit if none,
  156.     mov    dx,offset strstr
  157.     jz    gd1
  158.     dec    al        ;make 0-N,
  159.     mov    disk,al
  160.     call    seldsk        ;select,
  161.  
  162.     push    ds        ;save local DS,
  163.     mov    ah,1bh
  164.     int    33
  165.     pop    ds
  166.     mov    blkcnt,dx    ;save # blocks,
  167.     mov    secsize,cx    ;sector size,
  168.     mov    ah,0
  169.     mov    blksize,ax    ;secs/block.
  170.  
  171.     mov    fat16,0        ;assume small
  172.     cmp    blkcnt,4085    ;FAT then check
  173.     jb    gd0        ;for large
  174.     mov    fat16,1
  175.  
  176. gd0:    push    ds        ;now get the
  177.     mov    dl,disk
  178.     inc    dl        ;drive 1=A, b=2
  179.     mov    ah,50        ;FAT,
  180.     int    33        ;get the DPB,
  181.     mov    cx,[bx+15]    ;CX= sec count,
  182.     mov    ch,0
  183.     mov    dx,[bx+6]    ;DX= 1st sec,
  184.     pop    ds
  185.     mov    fatcnt,cx    ;save both,
  186.     mov    fatsec,dx
  187.  
  188.     mov    al,disk        ;AL= drive #,
  189.     mov    bx,offset fatbuf ;DS:BX= buffer
  190.     int    25h        ;read the FAT,
  191.     pop    ax        ;pop flags
  192.     mov    dx,offset bscstr
  193. gd1:    ret
  194.  
  195. wtstr    db    cr,lf,lf,'Wait ...$'
  196. strstr    db    cr,lf,'Must specify a disk drive.$'
  197. bscstr    db    cr,lf,'Bad FAT sector: disk not useable.$'
  198.  
  199. page
  200. ;
  201. ;Read the entire disk looking for bad blocks.
  202. ;When one is found, go mark it as an allocated
  203. ;bad block.
  204. ;
  205. findbad:
  206.     mov    block,0        ;1st block,
  207.     mov    badcnt,0    ;none yet,
  208.     mov    blkdsp,1
  209.  
  210. fb1:    dec    blkdsp        ;every 10th
  211.     jnz    fb1a        ;block
  212.     mov    blkdsp,10
  213.     mov    dx,offset blkstr ;type 'block '
  214.     call    pstr
  215.     mov    bx,block    ;block number,
  216.     call    outdec
  217.  
  218. fb1a:    call    readblk        ;read a block,
  219.     jnc    fb3        ;if bad, 
  220.     inc    badcnt        ;count it,
  221.  
  222.     mov    dx,offset blkstr ;type 'block '
  223.     call    pstr
  224.     mov    bx,block    ;block number,
  225.     call    outdec
  226.     mov    dx,offset badstr
  227.     call    pstr        ;type 'bad'
  228.     call    mapout        ;mark bad,
  229.     mov    dx,offset cntstr ;error if cant
  230.     jc    fb2
  231.     add    newbad,cx    ;count it,
  232.     mov    dx,offset alrstr
  233.     jcxz    fb2        ;already markd
  234.     mov    dx,offset mrkstr
  235. fb2:    call    pstr
  236. fb3:    inc    block        ;next block,
  237.     dec    blkcnt        ;another...
  238.     jnz    fb1        ;keep looking.
  239.     ret
  240.  
  241. blkstr    db    cr,'Block $'
  242. badstr    db    ' bad,$'
  243. alrstr    db    ' already marked.',lf,'$'
  244. mrkstr    db    ' mapped out.',lf,'$'
  245. cntstr    db    ' already used! I dont know'
  246.     db    ' which file.',lf,'$'
  247. page
  248. ;
  249. ;Map out the bad block. For a 16 bit FAT, its
  250. ;easy.
  251. ;
  252. mapout:    test    fat16,1
  253.     jz    mo0
  254.     mov    bx,block
  255.     shl    bx,1        ;times 2,
  256.     mov    ax,fatbuf[bx]    ;read fat ptr
  257. ;
  258. ;AX is the block number; if it's anything
  259. ;but 0000 or fff7, return with carry set, 
  260. ;indicating that its already used.
  261. ;
  262.     mov    cx,0        ;none mapped
  263.     cmp    ax,0fff7h    ;if fff7,
  264.     je    ml2        ;already marked
  265.     cmp    ax,0
  266.     stc
  267.     jnz    ml2        ;allocated
  268.     mov    word ptr fatbuf[bx],0fff7h
  269.     add    cx,1        ;(clr carry)
  270. ml2:    ret
  271. ;
  272. ;Mark the current block as bad in the FAT.
  273. ;Multiply the block number by 1.5 to find the
  274. ;block number, (actually *3, /2) and if not
  275. ;used, mark it bad. If used, report which file
  276. ;it's in. If it's already mapped as bad, 
  277. ;return CX =0, else return CX=1.
  278. ;
  279. mo0:    mov    bx,block    ;block,
  280.     shl    bx,1        ;times 2,
  281.     add    bx,block    ;times 3,
  282.     shr    bx,1        ;divide by 2,
  283.     mov    ax,fatbuf[bx]    ;get word,
  284. ;
  285. ;If carry is set, we want the high 12 bits in
  286. ;the word in AX, else the low 12 bits. Set CH
  287. ;as the shift count, DX as the mask.
  288. ;
  289.     mov    ch,0        ;assume low,
  290.     mov    dx,0fffh
  291.     jnc    mo1
  292.     mov    ch,4        ;else high 12,
  293.     mov    dx,0fff0h
  294. mo1:    and    ax,dx        ;mask it,
  295.     mov    cl,ch
  296.     shr    ax,cl        ;shift it,
  297. ;
  298. ;AX is the block number; if it's anything
  299. ;but 000 or ff7, return with carry set, 
  300. ;indicating that its already used.
  301. ;
  302.     cmp    ax,0ff7h    ;if ff7,
  303.     je    mo2        ;already marked
  304.     cmp    ax,0        ;if allocated,
  305.     je    mo3
  306.     stc            ;error!
  307. mo2:    mov    cx,0        ;none mapped,
  308.     ret
  309. ;
  310. ;Bad unused block. Mark as bad in the FAT.
  311. ;
  312. mo3:    mov    ax,0ff7h    ;marker,
  313.     mov    cl,ch
  314.     shl    ax,cl        ;shift it,
  315.     or    fatbuf[bx],ax    ;mark it.
  316.     mov    cx,1        ;1 mapped,
  317.     ret
  318. page
  319. ;
  320. ;Read one block, return carry set if read
  321. ;error. Leave the useless data in the buffer
  322. ;following the end of this program.
  323. ;
  324. readblk:
  325.     mov    ax,block    ;find start
  326.     mov    cx,blksize    ;sector,
  327.     mul    cx        ;CX= count,
  328.     mov    dx,ax        ;DX= sector,
  329.     mov    al,disk
  330.     mov    bx,offset blkbuf ;our buffer,
  331.     int    25h        ;read sectors,
  332.     pop    dx        ;pop flags,
  333.     ret
  334. page
  335. ;
  336. ;List the general info on the disk, like
  337. ;sector sizes, etc.
  338. ;
  339. liststat:
  340.     mov    dx,offset st1str
  341.     call    pstr
  342.     mov    al,disk
  343.     add    al,'A'
  344.     call    outa
  345.     mov    dx,offset st2str
  346.     call    pstr
  347.     mov    bx,blkcnt
  348.     call    outdec
  349.     mov    dx,offset st3str
  350.     call    pstr
  351.     mov    dx,offset st4astr
  352.     test    fat16,1
  353.     jz    ls1
  354.     mov    dx,offset st4bstr
  355. ls1:    call    pstr
  356.     ret
  357.  
  358. ;Disk A:, total of 12345 data blocks.
  359.  
  360. st1str    db cr,lf,'Disk $'
  361. st2str    db ':, total of $'
  362. st3str    db ' data blocks, $'
  363. st4astr    db '12 bit FAT.$'
  364. st4bstr    db '16 bit FAT.$'
  365. ;
  366. ;List out the bad things about this disk.
  367. ;
  368. listbad:
  369.     mov    dx,offset bd1str
  370.     call    pstr
  371.     mov    bx,badcnt
  372.     call    outdec
  373.     mov    dx,offset bd2str
  374.     call    pstr
  375.     mov    bx,newbad
  376.     call    outdec
  377.     mov    dx,offset bd3str
  378.     call    pstr
  379.     ret
  380.  
  381. ;Total of 12345 bad blocks, found 12234 more this pass.
  382. bd1str    db cr,'Total of $'        ;note no linefeed.
  383. bd2str    db ' bad blocks, found $'
  384. bd3str    db ' more this pass.$'
  385. page
  386. ;
  387. ;Generally useful system calls.
  388. ;
  389. pstr:    mov    ah,9
  390.     int    33
  391.     ret
  392. ;
  393. ;Type BX in decimal, suppressing leading
  394. ;zeros.
  395. ;
  396. outdec:    mov    cl,0    ;0 suppress flag,
  397.     mov    dx,10000
  398.     call    rsdiv
  399.     mov    dx,1000
  400.     call    rsdiv
  401.     mov    dx,100
  402.     call    rsdiv
  403.     mov    dx,10
  404.     call    rsdiv
  405.     mov    ch,bl
  406.     jmp    odf
  407.  
  408. rsdiv:    mov    ch,-1    ;iteration -1,
  409. rs1:    inc    ch    ;count,
  410.     sub    bx,dx    ;subtract,
  411.     jnc    rs1    ;til underflow,
  412.     add    bx,dx    ;adjust back,
  413.     cmp    ch,0    ;if non-zero,
  414.     jne    odf    ;type it,
  415.     test    cl,1    ;dont type 0's
  416.     jnz    odf    ;if leading,
  417.     ret
  418.  
  419. odf:    push    dx
  420.     mov    dl,ch
  421.     add    dl,'0'    ;ASCII,
  422.     mov    ah,2
  423.     int    33
  424.     pop    dx
  425.     mov    cl,1    ;no suppress,
  426.     ret
  427. page
  428. ;
  429. ;More system calls.
  430. ;
  431. seldsk:    mov    dl,al        ;select disk,
  432.     mov    ah,0eh
  433.     int    33
  434.     ret
  435.  
  436. getdsk:    mov    ah,19h
  437.     int    33
  438.     ret
  439.  
  440. initdsk:mov    ah,0dh
  441.     int    33
  442.     ret
  443.  
  444. ina:    mov    ah,0ch        ;char in with
  445.     mov    al,1        ;flush.
  446.     int    33
  447.     ret
  448.  
  449. outa:    mov    dl,al
  450.     mov    ah,2
  451.     int    33
  452.     ret
  453.  
  454. blkbuf    db 16384 dup (?)    ;cluster buffer
  455.  
  456. fatbuf label word        ;FAT buffer.
  457.  
  458. code ends
  459.  
  460.     end    scavenge
  461.